package util;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Map;

/**
 * @author liuli
 * http  https调用
 */
public class CommonHttpUtil {
    private static final String HTTP = "http";
    private static final String HTTPS = "https";
    private static final String UTF_8 = "UTF-8";
    private static SSLConnectionSocketFactory sslsf = null;
    private static PoolingHttpClientConnectionManager cm = null;
    private static SSLContextBuilder builder = null;
    private static CloseableHttpClient httpClient = null;
    private static Integer DEFAULT_TIMEOUT =3000;

    static {
        try {
            builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) {
                    return true;
                }
            });
            sslsf = new SSLConnectionSocketFactory(builder.build(), (s, sslSession) -> true);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register(HTTP, new PlainConnectionSocketFactory()).register(HTTPS, sslsf).build();
            cm = new PoolingHttpClientConnectionManager(registry);
            cm.setMaxTotal(200);
            cm.setDefaultMaxPerRoute(cm.getMaxTotal());
            //连接一段时间不用后，再次使用时，先进行连接检测
            cm.setValidateAfterInactivity(20000);
            HttpClientBuilder httpClientBuilder = HttpClients.custom();
            httpClientBuilder.setSSLSocketFactory(sslsf);
            RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(2000).setConnectionRequestTimeout(2000).build();
            httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
            httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
            httpClient = httpClientBuilder.setConnectionManager(cm).setConnectionManagerShared(true).build();
        } catch (Exception e) {
            System.out.println("PuBaoHttpUtil-error"+e.getMessage());
        }
    }

    /**
     *
     * @param url  请求地址
     * @param header  请求头
     * @param param   请求参数
     * @param timeout  超时时间
     * @return
     */
    public static String get(String url, Map<String, String> header, Map<String, String> param,Integer timeout) {
        if (timeout == null){
            timeout =DEFAULT_TIMEOUT;
        }
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(timeout)
                .setConnectTimeout(timeout)
                .setSocketTimeout(timeout)
                .build();
        if (!CollectionUtils.isEmpty(param)) {
            ArrayList<NameValuePair> list = new ArrayList<>();
            param.forEach((key, value) -> list.add(new BasicNameValuePair(key, value)));
            try {
                String paramStr = EntityUtils.toString(new UrlEncodedFormEntity(list, Consts.UTF_8));
                url = url + "?" + paramStr;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        RequestBuilder requestBuilder = RequestBuilder.get(url);
        return httpRequest(requestBuilder, header, config);
    }

    /**
     * 基础post发送json数据<br/>
     * 若params是String类型，则直接发送。<br/>
     * 否则，调用fastJson的toJSONString()转化成json再发送。
     *
     * @param url
     * @param header
     * @param params
     * @return
     */
    public static String postJson(String url, Map<String, String> header, Object params, Integer timeout) {
        if (timeout == null){
            timeout =DEFAULT_TIMEOUT;
        }
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(timeout)
                .setConnectTimeout(timeout)
                .setSocketTimeout(timeout)
                .build();
        RequestBuilder requestBuilder = RequestBuilder.post(url);
        if (params != null) {
            String jsonStr;
            if (params instanceof String) {
                jsonStr = (String) params;
            } else {
                jsonStr = JSONObject.toJSONString(params);
            }
            StringEntity entity = new StringEntity(jsonStr, Consts.UTF_8);
            entity.setContentEncoding(UTF_8);
            entity.setContentType("application/json");
            requestBuilder.setEntity(entity);
        }
        return httpRequest(requestBuilder, header, config);
    }

    /**
     * 创建请求
     * @param requestBuilder
     * @param header
     * @param config
     * @return
     */
    public static String httpRequest(RequestBuilder requestBuilder, Map<String, String> header, RequestConfig config) {
        if (!CollectionUtils.isEmpty(header)) {
            header.forEach((key, value) -> {
                if (StringUtils.hasText(key)) {
                    requestBuilder.addHeader(key, value);
                }
            });
        }
        if (config != null) {
            requestBuilder.setConfig(config);
        }
        HttpUriRequest request = requestBuilder.build();
        ResponseHandler<String> responseHandler = response -> {
            HttpEntity entity = response.getEntity();
            String responseEntity = entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : null;
            int status = response.getStatusLine().getStatusCode();
            if (status >= 200 && status < 300) {
                return responseEntity;
            } else {
                throw new HttpResponseException(status, "Unexpected response status: " + status);
            }
        };
        try {
            return httpClient.execute(request, responseHandler);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }








}
